﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LxCFD
{
    public class ComputeTask
    {
        private bool _IsForceInitialize = false;
        public void RunForceInitialization()
        {
            _IsForceInitialize = true;
            runComputation();
        }
        public void RunComputation()
        {
            _IsForceInitialize = false;
            runComputation();
        }
        private void runComputation()
        {
            if (AppRes.FvMesh == null)
            {
                LxConsole.Error("无网格");
                return;
            }
            MultiThreads.RunHostTask(hostTask);
        }
        private void hostTask()
        {
            //Stopwatch sw = new Stopwatch();
            //sw.Start();
            do
            {
                //1.初始化
                ResetTypes resetType = ResetTypes.None;
                if (_IsForceInitialize)
                {
                    resetType = ResetTypes.ClearFields;
                }
                else if (ComputeState.IsSettingChanged())
                {
                    resetType = ResetTypes.UpdateSolveCenter;
                }
                AppRes.StepsCenter.Reset(resetType);
                AppRes.MonitorCenter.Reset(resetType);
                AppRes.SolveCenter.Reset(resetType);
                if (_IsForceInitialize || ComputeState.IsSettingChanged())
                {
                    ComputeState.ReportSettingNoticed();
                    AppRes.FvMesh.CreateFields();
                    AppRes.SolveCenter.InitializeFields(_IsForceInitialize);
                }
                if (_IsForceInitialize) return;
                if (ComputeState.IsNeedInterrupt()) return;
                if (ComputeState.IsSettingChanged()) continue;
                //2.进入计算
                if (!AppRes.SolveCenter.IsTransient)
                {
                    run_steadyCal();
                }
                else
                {
                    if (AppRes.SolveCenter.TransientTime.IsImplicit)
                    {
                        run_transientImplicit();
                    }
                    else
                    {
                        run_transientExplicit();
                    }
                }
                if (ComputeState.IsNeedInterrupt()) return;
            } while (ComputeState.IsSettingChanged());
            AppRes.ExcuteCenter.ExcuteAfterAll();
            //sw.Stop();
            //LxConsole.Info(string.Format("用时/s： {0}", sw.Elapsed.TotalSeconds));
        }
        private void run_steadyCal()
        {
            do
            {
                AppRes.SolveCenter.Solve_Steady();
                AppRes.StepsCenter.MoveNextStep_Steady();
                AppRes.MonitorCenter.Monitor_Steady();
                if (ComputeState.IsNeedInterrupt() || ComputeState.IsSettingChanged()) return;
            } while (AppRes.StepsCenter.SteadyStep.IsContinue());
        }

        private void run_transientExplicit()
        {
            do
            {
                AppRes.SolveCenter.Solve_TransientExplicit();
                MoveNext_Transient();
                if (ComputeState.IsNeedInterrupt() || ComputeState.IsSettingChanged()) return;
            } while (AppRes.StepsCenter.TransientStep.IsContinue());

        }
        private void run_transientImplicit()
        {
            do
            {
                do
                {
                    AppRes.SolveCenter.Solve_TransientImplicit();
                    AppRes.StepsCenter.MoveNextStep_Steady();
                    AppRes.MonitorCenter.Monitor_Steady();
                    if (ComputeState.IsNeedInterrupt() || ComputeState.IsSettingChanged()) return;
                } while (AppRes.StepsCenter.SteadyStep.IsContinue());
                MoveNext_Transient();
                if (ComputeState.IsNeedInterrupt() || ComputeState.IsSettingChanged()) return;
            } while (AppRes.StepsCenter.TransientStep.IsContinue());
        }
        private void MoveNext_Transient()
        {
            AppRes.StepsCenter.MoveNextStep_Transient();
            AppRes.SolveCenter.TransientTime.MoveNextTimeStep();
            AppRes.SolveCenter.SaveOldValue();
            AppRes.MonitorCenter.Monitor_Transient();
        }
    }
}
